#include "../../utils/libcache/CacheWriteBack.hpp"
#include "../../engine/address.hpp"

#include <stdio.h>

#define PAGESIZE    4096
#define PAGE_BITS   12

static address_t nil;

CacheWriteBack<address_t> *
create (int cacheSize,int nsets) {
    return new CacheWriteBack<address_t>(cacheSize,nsets,PAGESIZE,false,1);
}

struct test_entry {
    address_t  page_num;
    CacheAccess hit;
};

typedef struct test_entry test_t;

void do_test (CacheWriteBack<address_t> * tlb, test_t * test)
{
    address_t evicted;
    Directory spam;

    for (int i = 0; test[i].page_num != 0; i++) {
        struct test_entry * entry = &test[i];
        // 12 bits for use page bits (4k)
        address_t address = entry->page_num << PAGE_BITS;
        CacheAccess response = tlb->read2(address, evicted, spam,spam, nil);
        if (response!=entry->hit) {
            printf("Error entry %4d: address %ld response %x expected %x evicted %ld\n",
                    i, entry->page_num.get(),response,entry->hit,evicted.get()>>PAGE_BITS);
        }
    }
}

int main (int argc, char * argv[]) {
    CacheWriteBack<address_t> * tlb = create(8,2);
    test_t a_test [] = {
            { 1, CACHE_MISS_NEW},
            { 1, CACHE_HIT_TOP},
            { 5, CACHE_MISS_NEW},
            { 5, CACHE_HIT_TOP },
            { 1, CACHE_HIT_TOP },
            { 9, CACHE_MISS_NEW},
            { 5, CACHE_HIT_TOP },
            { 1, CACHE_HIT_PUSH },
            { 25,CACHE_MISS_NEW }, // it must give an error, is an eviction
            { 0, CACHE_MISS_NEW }
        };
    do_test(tlb, a_test);
    return 1;
}
